library(tidyverse)
library(eph)
library(spatstat)
options(scipen = 9999)
options(dplyr.summarise.inform = FALSE)

Introducción

En la clase de hoy vamos a explorar nuevas formas de procesar una base de datos y visualizar nuestros resultados.

En particular, vamos a introducir el paquete plotly para generar visualizaciones interactivas.

Por último, vamos a trabajar con funciones e iteraciones para escalar nuestra capacidad de análisis de datos y presentación de resultados.

Visualización interactiva

La visualización interactiva va a permitir que los usuarios de nuestras visualizaciones puedan explorar nuestros resultados con mayor libertad. Es decir, van a permitir que cada usuario pueda analizar con mayor detalle lo que más le interesa.

Vamos a volver a trabajar con la base de EPH para encontrar la brecha salarial entre varones y mujeres para cada sector productivo, y luego vamos a graficarlo interactivamente.

base <- eph::get_microdata(year = 2019, 
                            trimester = 1,
                            type = "individual", 
                            destfile = "bases_fuentes/eph_2019_T1.rds")  %>% 
  organize_caes()%>%  #recodifica la variable que indica el sector de la ocupación
  select(ESTADO,"SEXO" = CH04, "Ing_Ocup_Principal"= P21, PONDIIO,caes_eph_label, "Horas" = PP3E_TOT, PONDERA) %>% 
  
  mutate(ESTADO = case_when(ESTADO == 1 ~ "Ocupado",
                            ESTADO == 2 ~ "Desocupado",
                            ESTADO == 3 ~ "Inactivo",
                            ESTADO == 4 ~ "Menor de 10 años"),
         SEXO = case_when(SEXO == 1 ~ "Varones",
                          SEXO == 2 ~ "Mujeres")) %>% 
  filter(Ing_Ocup_Principal != -9) %>%  #valor de no respuesta
  filter(ESTADO == "Ocupado")

Calculamos el ingreso medio de los trabajadores de cada sexo y sector, y luego la brecha. También vamos a tener en cuenta en qué sectores las mujeres tienen una participación mayor.

# Aclaración: el ponderador para la variable de ingreso de la ocupación
# proncipal es PONDIIO

ingresos <- base %>%
    filter(Ing_Ocup_Principal > 0) %>%
    group_by(SEXO, caes_eph_label) %>%
    summarise(Ingreso_medio = weighted.mean(Ing_Ocup_Principal, PONDIIO, na.rm = T)) %>%
    pivot_wider(id_cols = caes_eph_label, names_from = SEXO, values_from = Ingreso_medio) %>%
    mutate(Brecha = ((Varones - Mujeres)/Varones))

head(ingresos)
## # A tibble: 6 x 4
##   caes_eph_label                              Mujeres Varones  Brecha
##   <fct>                                         <dbl>   <dbl>   <dbl>
## 1 Actividades primarias                        26607.  38218.  0.304 
## 2 Industria manufacturera                      15351.  23005.  0.333 
## 3 Construccion                                 17316.  15654. -0.106 
## 4 Comercio                                     14916.  20068.  0.257 
## 5 Hoteles y restaurantes                       11952.  15263.  0.217 
## 6 Transporte, almacenamiento y comunicaciones  24106.  26564.  0.0925
feminizacion <- base %>%
    group_by(SEXO, caes_eph_label) %>%
    summarise(Casos = sum(PONDERA)) %>%
    ungroup() %>%
    group_by(caes_eph_label) %>%
    mutate(Total = sum(Casos), Prop = (Casos/Total) * 100) %>%
    filter(SEXO == "Mujeres") %>%
    select(caes_eph_label, Prop)

head(feminizacion)
## # A tibble: 6 x 2
## # Groups:   caes_eph_label [6]
##   caes_eph_label                               Prop
##   <fct>                                       <dbl>
## 1 Actividades primarias                       14.6 
## 2 Industria manufacturera                     30.8 
## 3 Construccion                                 2.73
## 4 Comercio                                    41.6 
## 5 Hoteles y restaurantes                      45.8 
## 6 Transporte, almacenamiento y comunicaciones 14.5
ingresos <- ingresos %>%
    left_join(., feminizacion, by = "caes_eph_label")

ingresos
## # A tibble: 14 x 5
##    caes_eph_label                                  Mujeres Varones  Brecha  Prop
##    <fct>                                             <dbl>   <dbl>   <dbl> <dbl>
##  1 Actividades primarias                            26607.  38218.  0.304  14.6 
##  2 Industria manufacturera                          15351.  23005.  0.333  30.8 
##  3 Construccion                                     17316.  15654. -0.106   2.73
##  4 Comercio                                         14916.  20068.  0.257  41.6 
##  5 Hoteles y restaurantes                           11952.  15263.  0.217  45.8 
##  6 Transporte, almacenamiento y comunicaciones      24106.  26564.  0.0925 14.5 
##  7 Servicios financieros, de alquiler y empresari~  23430.  27491.  0.148  42.5 
##  8 Administracion publica, defensa y seguridad so~  25803.  27890.  0.0748 41.6 
##  9 Ensenanza                                        19573.  22295.  0.122  75.9 
## 10 Servicios sociales y de salud                    24354.  34723.  0.299  66.5 
## 11 Servicio domestico                                6844.   5779. -0.184  96.4 
## 12 Otros servicios comunitarios, sociales y perso~  10810.  20931.  0.484  44.1 
## 13 Otras ramas                                      29610.  26477. -0.118  16.8 
## 14 Actividades no bien especificadas                23731.  28258.  0.160  23.2

plotly

Para graficar nuestros resultados, vamos a recurrir al paquete plotly. Este paquete nos ayuda a crear gráficos interactivos (y puede utilizarse en combinación con ggplot para transformar un gráfico no interactivo en un gráfico interactivo).

library(plotly)

En nuestro gráfico, vamos a graficar el ingreso medio de cada sector productivo para trabajadores de cada sexo, coloreando cada burbuja de acuerdo con la magnitud de la brecha, y determinando el tamaño de la burbuja según la proporción de trabajadoras mujeres en el sector.

#La sintaxis es un poco distinta a la de ggplot, más abajo podemos ver cómo recurrir a ella si nos resulto más cómoda

plot_ly(ingresos, x = ~Mujeres, y = ~Varones, 
        color = ~Brecha, colors = 'Spectral',
        type = 'scatter', mode = 'markers',  marker = list(size = ~Prop, opacity = 0.9),
        
        hoverinfo = 'text',
        text = ~paste(caes_eph_label, '<br>Mujeres:', paste0("$",round(Mujeres,1)), '<br>Varones:', paste0("$",round(Varones,1)), '<br>Brecha:', paste0(round(Brecha*100,1), "%"), '<br>Proporción de trabajadoras mujeres:', paste0(round(Prop,1), "%"))
        
        ) %>% 
       layout(title = 'Ingreso medio y brecha salarial por sector productivo',
         xaxis = list(showgrid = FALSE),
         yaxis = list(showgrid = FALSE),
         font = list(family ="Times New Roman"))

Prueben pasar el mouse por encima del gráfico, moverlo, hacer zoom, etc.

¿Qué análisis podemos hacer de la información representada?

ggplotly()

La función ggplotly() convierte nuestros ggplots en plotly. De esta forma, podemos tomar cualquiera de las visualizaciones que aprendimos a hacer la clase pasada y hacerla interactiva.

Por ejemplo:

feminizacion <- base %>%
    group_by(SEXO, caes_eph_label) %>%
    summarise(Casos = sum(PONDERA)) %>%
    ungroup() %>%
    group_by(caes_eph_label) %>%
    mutate(Total = sum(Casos), Prop = (Casos/Total) * 100) %>%
    filter(SEXO == "Mujeres") %>%
    select(caes_eph_label, Prop)


feminizacion
## # A tibble: 14 x 2
## # Groups:   caes_eph_label [14]
##    caes_eph_label                                       Prop
##    <fct>                                               <dbl>
##  1 Actividades primarias                               14.6 
##  2 Industria manufacturera                             30.8 
##  3 Construccion                                         2.73
##  4 Comercio                                            41.6 
##  5 Hoteles y restaurantes                              45.8 
##  6 Transporte, almacenamiento y comunicaciones         14.5 
##  7 Servicios financieros, de alquiler y empresariales  42.5 
##  8 Administracion publica, defensa y seguridad social  41.6 
##  9 Ensenanza                                           75.9 
## 10 Servicios sociales y de salud                       66.5 
## 11 Servicio domestico                                  96.4 
## 12 Otros servicios comunitarios, sociales y personales 44.1 
## 13 Otras ramas                                         16.8 
## 14 Actividades no bien especificadas                   23.2
#paleta de colores divina!
library(wesanderson)


plot_estatico <- feminizacion %>% 
  ggplot(.,aes(x = fct_reorder(caes_eph_label,Prop), y = Prop, 
        fill = Prop,
        #para que el hovertext nos quede como queremos 
        text = paste(caes_eph_label, '<br>Proporción de trabajadoras mujeres:', paste0(round(Prop,1), "%"))
  )
        )+
  geom_col(alpha = 0.9)+
  theme_minimal()+
  coord_flip()+
  labs(title = 'Tasa de feminización de las ramas de actividad',
       x="",y="")+
  scale_y_continuous(labels = function(x) paste0(x,"%"))+
  scale_x_discrete(labels = function(x) str_wrap(x,25))+
  scale_fill_gradientn(colours = wes_palette("Zissou1", 100, type = "continuous")) +
  guides(fill = "none")


plot_estatico

# lo hacemos interactivo

ggplotly(plot_estatico, tooltip = "text") %>%
    layout(font = list(family = "Times New Roman"))

Iteración y funciones

La iteración y las funciones nos van a permitir reducir la duplicación en el código (copiar y pegar las mismas instrucciones).

¿Por qué reducir la duplicación?

  • Es más fácil entender tu código (para vos en otro momento, o para un tercero).

  • Es más simple realizar cambios y encontrar errores.

Además, van a potenciar nuestro trabajo con R, permitiéndonos escalar la cantidad de procesamientos y visualizaciones que podemos obtener a partir del análisis de una base de datos en muy poco tiempo.

Iteraciones

La iteración es una herramienta para repetir la misma tarea con múltiples inputs (variables, conjuntos de datos, etc.).

Un loop es una estructura de código que nos permite aplicar iterativamente un mismo conjunto de comandos, variando el valor de una variable. Su estructura general es la siguiente:

for (variable in vector) {
    # Operaciones
}

El nombre que definamos para la variable debe ser el mismo que utilicemos para realizar las operaciones dentro del loop, pero puede ser cualquiera (x,i,planta,supercalifragil, etc).

Por ejemplo:

for (x in 1:5) {
    print(x * x)
}
## [1] 1
## [1] 4
## [1] 9
## [1] 16
## [1] 25

Lo que hizo el código fue crear una variable x, que fue tomando los valores 1, 2, 3, 4 y 5, y en cada caso multiplicándose por sí misma.

En nuestro loop pueden intervenir también objetos que hayamos definido previamente.

Por ejemplo:

b <- 10

for (x in 1:5) {
    print(x + b)
}
## [1] 11
## [1] 12
## [1] 13
## [1] 14
## [1] 15

Una herramienta que vamos a utilizar mucho es la función seq(), que permite generar una secuencia de números (que vamos a utilizar para iterar). Por default, si ingresamos un único número como argumento, genera una secuencia desde 1 hasta ese número.

seq(3)
## [1] 1 2 3
for (i in (seq(3))) {
    print(i)
}
## [1] 1
## [1] 2
## [1] 3

¿Cuándo podríamos usar esto? En operaciones de subsetting o slicing

# defino el vector
vec <- c("a", "b", "c")

# ¿cuántos elementos tiene?
length(vec)
## [1] 3
# Convierto cada elemento al mismo elemento en mayúscula
for (letra in (seq(length(vec)))) {
    vec[letra] <- toupper(vec[letra])
}

# ¿Cómo quedó?
vec
## [1] "A" "B" "C"

¿Qué pasó? Nuestro loop fue avanzando sobre los elementos de vec, reemplazándolos por el mismo valor en mayúscula. Por ejemplo, al vec[1] = “a”, lo transformó en “A”.

Aplicación sobre una base de datos

Veamos cómo puede ser útil para un procesamiento.

Si tenemos una base de datos con información sobre distintos tipos de población, podemos querer generar una medida resumen para cada segmento de la población.

Por ejemplo, supongamos que queremos llevar a cabo un análisis más detallado de la distribución de los ingresos por sexo para cada rama de actividad:

vector_valores <- unique(base$caes_eph_label)

# En esta lista vamos a guardar nuestros resultados
resultados <- list()

for (valor in (seq(length(vector_valores)))) {

    tabla_resumen <- base %>%
        filter(caes_eph_label == vector_valores[valor]) %>%
        filter(Ing_Ocup_Principal > 0) %>%
        group_by(SEXO) %>%
        summarise(sector = unique(caes_eph_label), max_ing = max(Ing_Ocup_Principal,
            na.rm = T), min_ing = min(Ing_Ocup_Principal, na.rm = T), media_ing = weighted.mean(Ing_Ocup_Principal,
            PONDIIO, na.rm = T), mediana_ing = weighted.median(Ing_Ocup_Principal,
            PONDIIO, na.rm = T))

    resultados[[valor]] <- tabla_resumen

}

# Veamos una de las tablas que generamos:

resultados[[3]]
## # A tibble: 2 x 6
##   SEXO    sector                           max_ing min_ing media_ing mediana_ing
##   <chr>   <fct>                              <int>   <int>     <dbl>       <dbl>
## 1 Mujeres Servicios financieros, de alqui~  100000     450    23430.       20000
## 2 Varones Servicios financieros, de alqui~  300000     300    27491.       22000

También podemos presentar nuestros resultados de una manera más amigable con quien está leyendo, o listo para copiar e incluir en un informe:

for (valor in (seq(length(vector_valores)))) {

    print(paste0("Para el sector ", unique(resultados[[valor]]$sector), ", el ingreso máximo alcanzado por un varón fue de $",
        resultados[[valor]]$max_ing[resultados[[valor]]$SEXO == "Varones"], ". Para las mujeres, por otro lado, fue de $",
        resultados[[valor]]$max_ing[resultados[[valor]]$SEXO == "Mujeres"]))


}
## [1] "Para el sector Actividades primarias, el ingreso máximo alcanzado por un varón fue de $250000. Para las mujeres, por otro lado, fue de $80000"
## [1] "Para el sector Construccion, el ingreso máximo alcanzado por un varón fue de $200000. Para las mujeres, por otro lado, fue de $75000"
## [1] "Para el sector Servicios financieros, de alquiler y empresariales, el ingreso máximo alcanzado por un varón fue de $300000. Para las mujeres, por otro lado, fue de $100000"
## [1] "Para el sector Transporte, almacenamiento y comunicaciones, el ingreso máximo alcanzado por un varón fue de $290000. Para las mujeres, por otro lado, fue de $70000"
## [1] "Para el sector Ensenanza, el ingreso máximo alcanzado por un varón fue de $100000. Para las mujeres, por otro lado, fue de $70000"
## [1] "Para el sector Administracion publica, defensa y seguridad social, el ingreso máximo alcanzado por un varón fue de $150000. Para las mujeres, por otro lado, fue de $200000"
## [1] "Para el sector Comercio, el ingreso máximo alcanzado por un varón fue de $300000. Para las mujeres, por otro lado, fue de $100000"
## [1] "Para el sector Servicio domestico, el ingreso máximo alcanzado por un varón fue de $15000. Para las mujeres, por otro lado, fue de $40500"
## [1] "Para el sector Industria manufacturera, el ingreso máximo alcanzado por un varón fue de $200000. Para las mujeres, por otro lado, fue de $200000"
## [1] "Para el sector Hoteles y restaurantes, el ingreso máximo alcanzado por un varón fue de $60000. Para las mujeres, por otro lado, fue de $35000"
## [1] "Para el sector Otros servicios comunitarios, sociales y personales, el ingreso máximo alcanzado por un varón fue de $250000. Para las mujeres, por otro lado, fue de $80000"
## [1] "Para el sector Servicios sociales y de salud, el ingreso máximo alcanzado por un varón fue de $390000. Para las mujeres, por otro lado, fue de $150000"
## [1] "Para el sector Otras ramas, el ingreso máximo alcanzado por un varón fue de $70000. Para las mujeres, por otro lado, fue de $60000"
## [1] "Para el sector Actividades no bien especificadas, el ingreso máximo alcanzado por un varón fue de $100000. Para las mujeres, por otro lado, fue de $80000"

Funciones

Retomamos lo introducido en la clase 2: la función es una forma de encapsular una serie de operaciones a las que vayamos a recurrir más de una vez, esta es su estructura general:

fun_ej <- function(argumentos) {
    # [se hace algún cómputo]
}

En este caso, vamos a utilizar esta herramienta -en conjunto con la iteración- para generar una serie de gráficos donde se visualice la distribución de los ingresos de las mujeres y los varones que se desempeñan en cada sector productivo de acuerdo con las horas que trabajan por semana.

Primero, vamos a generar los datos que vamos a graficar:

vector_valores <- unique(base$caes_eph_label)

# En esta lista vamos a guardar nuestros resultados
datos_graf <- list()

for (valor in (seq(length(vector_valores)))) {

    tabla_resumen <- base %>%
        filter(caes_eph_label == vector_valores[valor]) %>%
        filter(Ing_Ocup_Principal > 0) %>%
        filter(Horas > 0) %>%
        filter(Horas != 999) %>%
        group_by(SEXO, Ing_Ocup_Principal, Horas) %>%
        summarise(Casos = sum(PONDIIO, na.rm = T), sector = unique(caes_eph_label))

    datos_graf[[valor]] <- tabla_resumen

}

Veamos cómo queda algún elemento:

datos_graf[[2]]
## # A tibble: 688 x 5
## # Groups:   SEXO, Ing_Ocup_Principal [150]
##    SEXO    Ing_Ocup_Principal Horas Casos sector      
##    <chr>                <int> <int> <int> <fct>       
##  1 Mujeres               2000     3  2107 Construccion
##  2 Mujeres               3000    20   269 Construccion
##  3 Mujeres               3500    25    25 Construccion
##  4 Mujeres               4000    40   141 Construccion
##  5 Mujeres               5000     8   391 Construccion
##  6 Mujeres               5000    10   654 Construccion
##  7 Mujeres               6000     8    37 Construccion
##  8 Mujeres               6400    15   268 Construccion
##  9 Mujeres               6500    15   290 Construccion
## 10 Mujeres              10000    30  1571 Construccion
## # ... with 678 more rows

Luego, creamos nuestra función que grafica la información de una tabla:

crear_grafico = function(tabla) {

    ggplot(tabla, aes(x = Horas, y = Ing_Ocup_Principal, size = Casos, color = SEXO)) +
        geom_point(alpha = 0.4) + theme_minimal() + scale_color_manual(values = c("deeppink4",
        "mediumseagreen")) + scale_size_continuous(range = c(2, 15)) + scale_y_continuous(labels = function(x) paste0("$",
        x)) + facet_wrap(~SEXO, scales = "fixed", nrow = 1) + labs(title = unique(tabla$sector),
        y = "Ingreso de la ocupación principal", x = "Horas semanales trabajadas",
        color = "Sexo") + theme(legend.position = "bottom") + ggsave(paste0("clase6/graficos/",
        tolower(str_replace_all(unique(tabla$sector), " ", "_")), ".png"))

}

Finalmente, la aplicamos de forma iterativa:

for (i in seq(length(datos_graf))) {

    crear_grafico(datos_graf[[i]])

}

Los resultados de nuestro procesamiento están guardados en la carpeta graficos de la clase 6.

¡Terminamos! Ahora, vamos a la parte práctica.